package durst.data;

import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.security.providers.encoding.Md5PasswordEncoder;
import org.springframework.security.providers.encoding.PasswordEncoder;

import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.ForeignCollection;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.field.ForeignCollectionField;
import com.j256.ormlite.table.DatabaseTable;
import com.sdicons.json.mapper.JSONMapper;

import durst.data.dao.DaoFactory;
import durst.data.dao.impl.AccountDao;
import durst.data.json.AccountJSONHelper;
import durst.utils.ConfigParser;

@DatabaseTable(tableName = "Account", daoClass = AccountDao.class)
public class Account extends CSDEntity {
	public static final String USERNAME = "username";
	public static final String EMAIL = "email";
	
	public static final String USERNAME_UNIQUE = "UNIQUE_Account_Username";
	public static final String EMAIL_UNIQUE = "UNIQUE_Account_Email";
	
	static { 
		JSONMapper.addHelper(new AccountJSONHelper());
	}

	@DatabaseField(generatedId = true)
	private int id;

	@DatabaseField(canBeNull = false, columnName = USERNAME, uniqueIndex = true, uniqueIndexName = USERNAME_UNIQUE)
	private String username;

	@DatabaseField(canBeNull = false, columnName = EMAIL, uniqueIndex = true, uniqueIndexName = EMAIL_UNIQUE)
	private String email;

	@DatabaseField(canBeNull = false)
	private String password;

	@DatabaseField(canBeNull = false)
	private String firstName;

	@DatabaseField(canBeNull = false)
	private String lastName;

	@ForeignCollectionField
	private ForeignCollection<Invite> invitedTo;

	private final static String SALT = ConfigParser
			.getProp("durst.acccount.password.salt");

	private static PasswordEncoder encoder = new Md5PasswordEncoder();

	public Account() {
	}

	public Account(String username, String email, String password,
			String firstName, String lastName, boolean encode) {
		this.username = username;
		this.email = email;
		this.password = encode ? encoder.encodePassword(password, SALT) : password;
		this.firstName = firstName;
		this.lastName = lastName;
	}

	public String getFullName() { 
		StringBuilder builder = new StringBuilder(); 
		builder.append(firstName);
		builder.append(" ");
		builder.append(lastName);
		return builder.toString();
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getFirstName() {
		return firstName;
	}

	public boolean validatePassword(String password) {
		return encoder.isPasswordValid(this.password, password, SALT);
	}

	public void changePassword(String password) {
		this.password = encoder.encodePassword(password, SALT);
	}

	public ForeignCollection<Invite> getInvitedTo() {
		if (invitedTo == null)
			try {
				DaoFactory.getInstance().createDao(Account.class).refresh(this);
			}
			catch (SQLException e) {
				Logger.getLogger(Account.class).error("Count not auto refresh ForeignCollection");
			}
		return invitedTo;
	}

	public List<UserCalendar> getCalendars() {
		try {
			Dao<UserCalendar, Integer> dao = DaoFactory.getInstance().createDao(UserCalendar.class);
			return dao.queryBuilder().where().eq("owner_id", id).query();
		}
		catch (SQLException err) {
			Logger.getLogger(Event.class).error("SQLException in getFiles()" + err.getMessage());
			return new LinkedList<UserCalendar>();
		}
	}
}